﻿using EM.FrameWork.Paging;
using EM.OA.DAL;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity.Infrastructure;
using System.Data.Objects;
using System.Linq;
using System.Linq.Expressions;

namespace EM.OA.BLL
{
    /// <summary>
    /// 业务逻辑层基类
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public abstract class BLLBase<TEntity> where TEntity : class
    {
        /// <summary>
        /// 增加实体
        /// </summary>
        /// <param name="entity">实体信息</param>
        /// <returns></returns>
        public bool Add(TEntity entity)
        {
            using (var db = new EMOAContext())
            {
                db.Set<TEntity>().Add(entity);
                return db.SaveChanges() > 0;
            }
        }

        /// <summary>
        /// 批量增加实体
        /// </summary>
        /// <param name="entitys">实体信息</param>
        /// <returns></returns>
        public bool Add(List<TEntity> entitys)
        {
            using (var db = new EMOAContext())
            {
                entitys.ForEach(p =>
                {
                    db.Set<TEntity>().Add(p);
                });
                return db.SaveChanges() > 0;
            }
        }

        /// <summary>
        /// 修改实体
        /// </summary>
        /// <param name="entity">实体信息</param>
        /// <returns></returns>
        public bool Update(TEntity entity)
        {
            using (var db = new EMOAContext())
            {
                db.Entry(entity).State = EntityState.Modified;
                return db.SaveChanges() > 0;
            }
        }

        /// <summary>
        /// 修改实体
        /// </summary>
        /// <param name="entitys">实体信息</param>
        /// <returns></returns>
        public bool Update(List<TEntity> entitys)
        {
            using (var db = new EMOAContext())
            {
                entitys.ForEach(p =>
                {
                    db.Entry(p).State = EntityState.Modified;
                });
                return db.SaveChanges() > 0;
            }
        }

        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="keyID">实体的主键值</param>
        /// <returns></returns>
        public bool Delete(object keyID)
        {
            using (var db = new EMOAContext())
            {
                TEntity model = db.Set<TEntity>().Find(keyID);
                if (model != null)
                {
                    db.Set<TEntity>().Remove(model);
                    return db.SaveChanges() > 0;
                }
                else
                {
                    return false;
                }
            }
        }

        /// <summary>
        /// 批量删除实体
        /// </summary>
        /// <param name="keyIDs">多个实体的主键值</param>
        /// <returns></returns>
        public bool Delete(List<object> keyIDs)
        {
            using (var db = new EMOAContext())
            {
                keyIDs.ForEach(p =>
                {
                    TEntity model = db.Set<TEntity>().Find(p);
                    if (model != null)
                    {
                        db.Set<TEntity>().Remove(model);
                    }
                });
                return db.SaveChanges() > 0;
            }
        }

        /// <summary>
        /// 根据条件删除
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public bool Delete(Func<TEntity, bool> where)
        {
            using (var db = new EMOAContext())
            {
                db.Set<TEntity>().Where(where).ToList().ForEach(
                    p => db.Set<TEntity>().Remove(p)
                 );
                return db.SaveChanges() > 0;
            }
        }

        /// <summary>
        /// 获取实体
        /// </summary>
        /// <param name="keyID">实体的主键值</param>
        /// <returns></returns>
        public TEntity GetEntity(object keyID)
        {
            using (var db = new EMOAContext())
            {
                return db.Set<TEntity>().Find(keyID);
            }
        }

        /// <summary>
        /// 获取所有实体列表
        /// </summary>
        /// <param name="where">查询条件</param>
        /// <param name="orderBy">排序字段</param>
        /// <param name="isOrderByDescending">是否降序</param>
        /// <returns></returns>
        public List<TEntity> GetList(Func<TEntity, bool> where = null, Func<TEntity, object> orderBy = null, bool isOrderByDescending = false)
        {
            using (var db = new EMOAContext())
            {
                string primaryKey = GetPrimaryKey<TEntity>();
                if (where == null)
                {
                    if (orderBy == null)
                        return db.Set<TEntity>().OrderBy(p => primaryKey).ToList();
                    else
                    {
                        if (isOrderByDescending)
                            return db.Set<TEntity>().OrderByDescending(orderBy).ToList();
                        else
                            return db.Set<TEntity>().OrderBy(orderBy).ToList();
                    }
                }
                else
                {
                    if (orderBy == null)
                        return db.Set<TEntity>().Where(where).OrderBy(p => primaryKey).ToList();
                    else
                    {
                        if (isOrderByDescending)
                            return db.Set<TEntity>().Where(where).OrderByDescending(orderBy).ToList();
                        else
                            return db.Set<TEntity>().Where(where).OrderBy(orderBy).ToList();
                    }
                }
            }
        }

        /// <summary>
        /// 获取单表分页实体列表
        /// </summary>
        /// <param name="pageIndex">页索引</param>
        /// <param name="pageSize">页大小</param>
        /// <returns></returns>
        public PagedList<TEntity> GetPagedList(int pageIndex, int pageSize)
        {
            using (var db = new EMOAContext())
            {
                string primaryKey = GetPrimaryKey<TEntity>();
                return db.Set<TEntity>().OrderBy(p => primaryKey).ToPagedList(pageIndex, pageSize);
            }
        }

        /// <summary>
        /// 根据查询条件获取单表分页实体列表
        /// </summary>
        /// <param name="pageIndex">页索引</param>
        /// <param name="pageSize">页大小</param>
        /// <param name="where">查询表达式</param>
        /// <param name="orderBy">排序字段</param>
        /// <param name="isOrderByDescending">是否降序</param>
        /// <returns></returns>
        public PagedList<TEntity> GetPagedList(int pageIndex, int pageSize, Func<TEntity, bool> where = null, Func<TEntity, object> orderBy = null, bool isOrderByDescending = false)
        {
            using (var db = new EMOAContext())
            {
                string primaryKey = GetPrimaryKey<TEntity>();
                if (where == null)
                {
                    if (orderBy == null)
                        return db.Set<TEntity>().OrderBy(p => primaryKey).ToPagedList(pageIndex, pageSize);
                    else
                    {
                        if (isOrderByDescending)
                            return db.Set<TEntity>().OrderByDescending(orderBy).ToPagedList(pageIndex, pageSize);
                        else
                            return db.Set<TEntity>().OrderBy(orderBy).ToPagedList(pageIndex, pageSize);
                    }
                }
                else
                {
                    if (orderBy == null)
                        return db.Set<TEntity>().Where(where).OrderBy(p => primaryKey).ToPagedList(pageIndex, pageSize);
                    else
                    {
                        if (isOrderByDescending)
                            return db.Set<TEntity>().Where(where).OrderByDescending(orderBy).ToPagedList(pageIndex, pageSize);
                        else
                            return db.Set<TEntity>().Where(where).OrderBy(orderBy).ToPagedList(pageIndex, pageSize);
                    }
                }
            }
        }

        /// <summary>
        /// 获取实体的主键
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        private string GetPrimaryKey<T>() where T : class
        {
            using (var db = new EMOAContext())
            {
                ObjectContext objectContext = ((IObjectContextAdapter)db).ObjectContext;
                ObjectSet<T> set = objectContext.CreateObjectSet<T>();
                IEnumerable<string> keyNames = set.EntitySet.ElementType.KeyMembers.Select(k => k.Name);

                if (keyNames.Count() == 0)
                    throw new Exception("No primary key");

                string primaryKeyName = "";
                foreach (string item in keyNames)
                {
                    primaryKeyName = item.ToString();
                    break;
                }
                return primaryKeyName;
            }
        }
    }
}
